package com.ruge.tool.map;

import com.ruge.tool.str.StringTool;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

/**
 * MapTool 工具类
 *
 * @author ruge.wu
 * @since 2021/7/20 21:17
 **/
public class MapTool {
    /**
     * 新建map
     *
     * @return 返回key是string value是Object的map
     */
    public static Map<String, Object> newHashMap() {
        return new HashMap<>(16);
    }

    /**
     * 新建map
     *
     * @param v        value
     * @param <V>      value的泛型
     * @return HashMap
     */
    public static <V> Map<String, V> newHashMap(V v) {
        return new HashMap<>(16);
    }

    /**
     * 新建map
     *
     * @param k   key
     * @param v   value
     * @param <K> key的泛型
     * @param <V> value的泛型
     * @return HashMap
     */
    public static <K, V> Map<K, V> newHashMap(K k, V v) {
        return new HashMap<>(16);
    }

    /**
     * 将url转换成map
     *
     * @param param 待转换url
     * @return 转换后的map
     */
    public static Map<String, String> getUrlParams(String param) {
        Map<String, String> map = new HashMap<>(16);
        if (StringTool.isBlank(param)) {
            return map;
        }
        String[] params;
        // 关键字 ?
        String keyword1 = "?";
        // 关键字 &
        String keyword2 = "&";
        // 关键字 =
        String keyword3 = "=";
        if (param.contains(keyword1)) {
            params = param.substring(param.indexOf(keyword1) + 1).split(keyword2);
        } else {
            params = param.split(keyword2);
        }
        for (String s : params) {
            String[] p = s.split(keyword3);
            if (p.length == 2) {
                map.put(p[0], p[1]);
            }
        }
        return map;
    }


    /**
     * 将map转换成url
     *
     * @param map 待转换的map
     * @return 转换后的url
     */
    public static String buildUrlParams(Map<String, String> map) {
        if (map == null) {
            return "";
        }
        // 关键字 &
        String keyword1 = "&";
        // 关键字 =
        String keyword2 = "=";

        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            sb.append(entry.getKey()).append(keyword2).append(entry.getValue()).append(keyword1);
        }
        String s = sb.toString();
        if (s.endsWith(keyword1)) {
            s = StringUtils.substringBeforeLast(s, keyword1);
        }
        return s;
    }


    /**
     * 根据map的key进行排序
     *
     * @param map 待排序map
     * @param <K> key的泛型
     * @param <V> value的泛型
     * @return 排序后的map
     */
    public static <K extends Comparable<? super K>, V> Map<K, V> sortByKey(Map<K, V> map) {
        return sortByKey(map, true);
    }


    /**
     * 根据map的key进行排序
     *
     * @param map   待排序map
     * @param <K>   key的泛型
     * @param <V>   value的泛型
     * @param isAsc 是否是升序
     * @return 排序后的map
     */
    public static <K extends Comparable<? super K>, V> Map<K, V> sortByKey(Map<K, V> map, Boolean isAsc) {
        Map<K, V> result = new LinkedHashMap<>();
        if (isAsc) {
            map.entrySet().stream()
                    .sorted(Map.Entry.comparingByKey())
                    .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        } else {
            map.entrySet().stream()
                    .sorted(Map.Entry.<K, V>comparingByKey().reversed())
                    .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        }

        return result;
    }


    /**
     * 根据map的key进行排序
     *
     * @param map 待排序map
     * @param <K> key的泛型
     * @param <V> value的泛型
     * @return 排序后的map
     */
    public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
        return sortByValue(map, true);
    }

    /**
     * 根据map的value进行排序
     *
     * @param map   待排序map
     * @param <K>   key的泛型
     * @param <V>   value的泛型
     * @param isAsc 是否是升序
     * @return 排序后的map
     */
    public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map, Boolean isAsc) {
        Map<K, V> result = new LinkedHashMap<>();

        if (isAsc) {
            map.entrySet().stream()
                    .sorted(Map.Entry.comparingByValue())
                    .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        } else {
            map.entrySet().stream()
                    .sorted(Map.Entry.<K, V>comparingByValue().reversed())
                    .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        }
        return result;
    }

}
